package com.dcrain.api.authz.common.utils;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.dcrain.api.authz.common.ApiConstant;

public class SignatureUtils {
	private static final Logger logger = LoggerFactory.getLogger(SignatureUtils.class);

	public static String getSign(String jsonStr, String nonce, String signKey) {
		return MD5Utils.getMD5(MD5Utils.getMD5(jsonStr) + nonce + signKey);
	}
    /**
     * 规则：简单参数（非嵌套的JSONObject、JSONArray）
     *  按KEY进行升幂排序得出sign=MD5(MD5(key=value&key=value&signKey)+nonce)
     * 注：两次MD5
     * @param signMap
     * @param nonce
     * @param signKey
     * @return
     */
	public static String getSign(Map signMap, String nonce, String signKey) {
		Map<String, String> map = new TreeMap();
		map.putAll(signMap);
		StringBuilder sb = new StringBuilder();
		for (Map.Entry<String, String> s : map.entrySet()) {
			String key = s.getKey();
			Object value = s.getValue();
			if (value == null) {// 过滤空值
				continue;
			} else if (ApiConstant.SIGN.equalsIgnoreCase(key)) {// 去掉sign
				continue;
			} if(value instanceof JSONObject) {
				continue;
			}else if(value instanceof JSONArray) {
				continue;
			}else {
				// 拼接
				sb.append(key).append("=").append(value).append("&");
			}
		}
		// 拼接密钥
		sb.append(signKey);
		logger.info("signstr:" + sb.toString());
//		System.out.println("signstr:=>"+sb.toString());
//		System.out.println(MD5Utils.getMD5(sb.toString()));
		String nsign = MD5Utils.getMD5(MD5Utils.getMD5(sb.toString()) + nonce);
		return nsign;
	}
	
	public static boolean validateSign(Map map,String nonce,String signKey,String sign) {
		String nSign = getSign(map, nonce, signKey);
		logger.info("sign:"+sign+" 生成的nSign:"+nSign+".");
		return sign.equals(nSign);
		
	}
	
	private static List sortJsonArray(JSONArray array) {
		if(array==null||array.size()<1)
			return null;
		
		List list = new ArrayList();
		for (int i = 0; i < array.size(); i++) {
			Object obj = array.get(i);
			if(obj instanceof JSONObject) {
				list.add(sortJsonObject((JSONObject)obj));
			}else if(obj instanceof JSONArray) {
				list.add(sortJsonArray((JSONArray)obj));
			}else {
				list.add(obj);
			}
		}
		return list;
	} 
	private static Map sortJsonObject(JSONObject obj) {
		Map<String, Object> map = new TreeMap();
		Iterator<String> it = obj.keySet().iterator();
		while(it.hasNext()) {
			String key = it.next();
			Object value = obj.get(key);
			if(value instanceof JSONObject) {
				map.put(key, sortJsonObject((JSONObject)value));
			}else if(value instanceof JSONArray) {
				map.put(key,sortJsonArray((JSONArray)value));
			}else {
				map.put(key, value);
			}
		}
		return map;
	}
//	public static void main(String[] args) {
//		String json="{   \"t1\":\"\", \"t3\":1, \"t2\":{\"B2\":3,\"b4\":1,\"A\":1,    \"a1\":\"\",      \"a3\":\"\",\"a2\":\"\"},\"id\":20,\"nickName\":\"nc\",\"helperCode\":\"a\",\"wechatCode\":\"wchatCode1\",\"wechatMobile\":\"a1\",\"wechatQrcode\":\"weQrcod1e\",\"helperCityArray\":[{\"cityCode\":\"120100\",\"cityName\":\"天津市\"},{\"cityName\":\"北京市\",\"cityCode\":\"110100\"},{\"cityCode\":\"610100\",\"cityName\":\"西安市\"}]}";
//		Map map = JSONObject.parseObject(json,Feature.OrderedField);
//		String sign = getSign(map, "12","11");
//		System.out.println(sign);
//		
//		JSONObject jsonObj = JSONObject.parseObject(json,Feature.OrderedField);
//		
//		Map m = sortJsonObject(jsonObj);
//		Set keySet  = m.keySet();
//		for (Iterator iterator = keySet.iterator(); iterator.hasNext();) {
//			String key = (String) iterator.next();
//			Object value =m.get(key);
//			System.out.println(key+" "+value);
//		}
//		sign = getSign(m, "12","11");
//		System.out.println(sign);
//	}
}
//
//class ReqObj{
//	private String artisanId;
//	private String cityCode;
//	public String getArtisanId() {
//		return artisanId;
//	}
//	public void setArtisanId(String artisanId) {
//		this.artisanId = artisanId;
//	}
//	public String getCityCode() {
//		return cityCode;
//	}
//	public void setCityCode(String cityCode) {
//		this.cityCode = cityCode;
//	}
//	@Override
//	public String toString() {
//		return "ReqObj [artisanId=" + artisanId + ", cityCode=" + cityCode + "]";
//	}
//}
